package com.ruoyi.ams.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;

import com.ruoyi.ams.domain.AmsAssetInventory;
import com.ruoyi.ams.domain.AmsAssetInventoryDetail;
import com.ruoyi.ams.service.*;
import com.ruoyi.common.core.domain.KeyValueVo;
import com.ruoyi.common.core.domain.R;
import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.core.domain.entity.SysUser;
import com.ruoyi.common.core.domain.model.AmsAssetType;
import com.ruoyi.common.core.domain.model.AmsOwnAddress;
import com.ruoyi.common.core.domain.model.AmsOwnAsset;
import com.ruoyi.common.core.utils.poi.ExcelUtil;
import com.ruoyi.common.core.web.controller.BaseController;
import com.ruoyi.common.core.web.domain.AjaxResult;
import com.ruoyi.common.core.web.page.TableDataInfo;
import com.ruoyi.common.log.annotation.Log;
import com.ruoyi.common.log.enums.BusinessType;
import com.ruoyi.security.annotation.PreAuthorize;
import com.ruoyi.system.controller.SysDeptController;
import com.ruoyi.system.controller.SysUserController;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;
import  com.ruoyi.asms.service.IAsmsAssetFullInfoService;
/**
 * 盘点单Controller
 *
 * @author yfkj
 * @date 2022-05-16
 */
@RestController
@RequestMapping("/ams/inventory")
public class AmsAssetInventoryController extends BaseController {
    @Autowired
    private IAmsAssetInventoryService amsAssetInventoryService;

    @Autowired
    private IAmsAssetTypeService amsAssetTypeService;
    @Autowired
    private IAsmsAssetFullInfoService assetFullInfoService;
    @Autowired
    private IAmsOwnAddressService amsOwnAddressService;
    @Autowired
    private AmsReusingService amsReusingService;
    @Autowired
    IAmsOwnAssetService amsOwnAssetService;
    @Autowired
    IAmsAssetInventoryDetailService amsAssetInventoryDetailService;
//    @Autowired
//    private RemoteUserService remoteUserService;
//    @Autowired
//    private RemoteDeptService remoteDeptService;
    @Autowired
    private SysUserController userController;
    @Autowired
    private SysDeptController deptController;
    /**
     * 查询盘点单列表
     */
    @PreAuthorize
    //@PreAuthorize(hasPermi = "ams:inventory:list")
    @ApiOperation(value = "获取盘点单列表")
    @GetMapping("/getAmsAssetInventoryList")
    public TableDataInfo getAmsAssetInventoryList(AmsAssetInventory amsAssetInventory) {
        QueryWrapper<AmsAssetInventory> wrapper = new QueryWrapper<>();
        if (amsAssetInventory.getStatus() != null) {
            wrapper.eq(AmsAssetInventory.STATUS, amsAssetInventory.getStatus());
        }
        wrapper.orderByDesc(AmsAssetInventory.START_TIME);
        startPage();
        List<AmsAssetInventory> list = amsAssetInventoryService.list(wrapper);

        CompletableFuture<R<Map<Long, SysUser>>> future1 = CompletableFuture.supplyAsync(() ->
               userController.getAllUsers());

        CompletableFuture<R<Map<Long, SysDept>>> future2 = CompletableFuture.supplyAsync(() ->
               deptController.getAllDeptsMap());

        CompletableFuture<List<AmsAssetType>> future3 = CompletableFuture.supplyAsync(() ->
                amsAssetTypeService.list(new QueryWrapper<AmsAssetType>()
                        .select(AmsAssetType.ASSET_TYPE_ID, AmsAssetType.ASSET_TYPE_NAME)));

        CompletableFuture<List<AmsOwnAddress>> future5 = CompletableFuture.supplyAsync(() ->
                amsOwnAddressService.list(new QueryWrapper<AmsOwnAddress>()
                        .select(AmsOwnAddress.ADDRESS_ID, AmsOwnAddress.FULL_NAME)));

        HashMap<Long, String> typeMap = new HashMap<>();
        HashMap<Long, String> addressMap = new HashMap<>();
        R<Map<Long, SysUser>> allUsers = new R<>();
        R<Map<Long, SysDept>> allDeptsMap = new R<>();
        List<AmsAssetType> types = new ArrayList<>();
        List<AmsOwnAddress> addresses = new ArrayList<>();
        try {
            allUsers = future1.get();
            if (allUsers.getCode() == R.FAIL) {
                return amsReusingService.resovleError();
            }
            allDeptsMap = future2.get();
            if (allDeptsMap.getCode() == R.FAIL) {
                return amsReusingService.resovleError();
            }
            types = future3.get();
            addresses = future5.get();
        } catch (InterruptedException | ExecutionException e) {
            e.printStackTrace();
        }

        for (AmsAssetType type : types) {
            typeMap.put(type.getAssetTypeId(), type.getAssetTypeName());
        }

        for (AmsOwnAddress address : addresses) {
            addressMap.put(address.getAddressId(), address.getFullName());
        }

        Map<Long, SysUser> userMap = allUsers.getData();
        Map<Long, SysDept> deptMap = allDeptsMap.getData();
        SimpleDateFormat fmt = new SimpleDateFormat("yyyy.MM.dd");

        for (AmsAssetInventory inventory : list) {
            if (inventory.getAdminUserIds() != null) {
                String[] adminUserIds = inventory.getAdminUserIds().split(",");
                long[] adminIds = Arrays.stream(adminUserIds).mapToLong(Long::parseLong).toArray();
                StringBuilder adminsName = new StringBuilder();
                int flag = 0;
                for (long adminId : adminIds) {
                    flag++;
                    if (userMap.get(adminId) != null) {
                        adminsName.append(userMap.get(adminId).getNickName());
                    }

                    if (flag < adminIds.length) {
                        adminsName.append(",");
                    }
                }
                inventory.setAdminUsersName(adminsName.toString());
            }
            if (inventory.getStartTime() != null) {
                inventory.setStartTimeStr(fmt.format(new Date(inventory.getStartTime())));
            }
            if (inventory.getEndTime() != null) {
                inventory.setEndTimeStr(fmt.format(new Date(inventory.getEndTime())));
            }
            if (inventory.getAssetTypeIds() != null) {
                String[] typeIdsStr = inventory.getAssetTypeIds().split(",");
                long[] typeIds = Arrays.stream(typeIdsStr).mapToLong(Long::parseLong).toArray();
                StringBuilder typesName = new StringBuilder();
                int flag = 0;
                for (long typeId : typeIds) {
                    flag++;
                    typesName.append(typeMap.get(typeId));
                    if (flag < typeIds.length) {
                        typesName.append(",");
                    }
                }
                inventory.setAssetTypesName(typesName.toString());
            }
            if (inventory.getUseDeptIds() != null) {
                String[] useDeptIdsStr = inventory.getUseDeptIds().split(",");
                long[] useDeptIds = Arrays.stream(useDeptIdsStr).mapToLong(Long::parseLong).toArray();
                StringBuilder useDeptsName = new StringBuilder();
                int flag = 0;
                for (long useDeptId : useDeptIds) {
                    flag++;
                    if (deptMap.get(useDeptId) != null) {
                        useDeptsName.append(deptMap.get(useDeptId).getDeptFullName());
                    }
                    if (flag < useDeptIds.length) {
                        useDeptsName.append(",");
                    }
                }
                inventory.setUseDeptsName(useDeptsName.toString());
            }
            if (inventory.getOwnDeptIds() != null) {
                String[] ownDepeIdsStr = inventory.getOwnDeptIds().split(",");
                long[] ownDeptIds = Arrays.stream(ownDepeIdsStr).mapToLong(Long::parseLong).toArray();
                int flag = 0;
                StringBuilder ownDeptsName = new StringBuilder();
                for (long ownDeptId : ownDeptIds) {
                    flag++;
                    if (deptMap.get(ownDeptId) != null) {
                        ownDeptsName.append(deptMap.get(ownDeptId).getDeptFullName());
                    }
                    if (flag < ownDeptIds.length) {
                        ownDeptsName.append(",");
                    }
                }
                inventory.setOwnDeptsName(ownDeptsName.toString());
            }
            if (inventory.getAddressIds() != null) {
                String[] addressIdsStr = inventory.getAddressIds().split(",");
                long[] addressIds = Arrays.stream(addressIdsStr).mapToLong(Long::parseLong).toArray();
                int flag = 0;
                StringBuilder addressNames = new StringBuilder();
                for (long addressId : addressIds) {
                    flag++;
                    addressNames.append(addressMap.get(addressId));
                    if (flag < addressIds.length) {
                        addressNames.append(",");
                    }
                }
                inventory.setAddressNames(addressNames.toString());
            }
        }


        List<Long> inventoryIds = new LinkedList<>();
        HashMap<Long, AmsAssetInventory> map = new HashMap<>();
        for (AmsAssetInventory assetInventory : list) {
            inventoryIds.add(assetInventory.getInventoryId());
            assetInventory.setInventorying(0);
            assetInventory.setInventoried(0);
            assetInventory.setInventoryLoss(0);
            assetInventory.setInventoryProfit(0);
            map.put(assetInventory.getInventoryId(), assetInventory);
        }

        List<AmsAssetInventoryDetail> detailList = amsAssetInventoryDetailService.list(new QueryWrapper<AmsAssetInventoryDetail>().in(AmsAssetInventoryDetail.INVENTORY_ID, inventoryIds));

        for (AmsAssetInventoryDetail assetInventoryDetail : detailList) {
            AmsAssetInventory assetInventory = map.get(assetInventoryDetail.getInventoryId());
            if (assetInventory == null) {
                continue;
            }
            switch (assetInventoryDetail.getStatus()) {
                case "0":
                    assetInventory.setInventorying(assetInventory.getInventorying() + 1);
                    break;
                case "1":
                    assetInventory.setInventoried(assetInventory.getInventoried() + 1);
                    break;
                case "2":
                    assetInventory.setInventoryLoss(assetInventory.getInventoryLoss() + 1);
                    break;
                case "3":
                    assetInventory.setInventoryProfit(assetInventory.getInventoryProfit() + 1);
                    break;
            }
        }


        return getDataTable(list, 10);

    }


    /**
     * 获取盘点单详细信息
     */
    @PreAuthorize
    //@PreAuthorize(hasPermi = "ams:inventory:query")
    //@ApiOperation(value = "获取盘点单详情")
    @GetMapping(value = "/getAmsAssetInventoryById")
    public AjaxResult getAmsAssetInventoryById(@RequestParam("inventoryId") Long inventoryId) {
        return AjaxResult.success(amsAssetInventoryService.selectAmsAssetInventoryByInventoryId(inventoryId));
    }

    /**
     * 新增盘点单
     */
    @PreAuthorize
    //@PreAuthorize(hasPermi = "ams:inventory:add")
    @Log(title = "盘点单", businessType = BusinessType.INSERT)
    @ApiOperation(value = "新增盘点单")
    @PostMapping(value = "/addAmsAssetInventory")
    public AjaxResult addAmsAssetInventory(@RequestBody AmsAssetInventory amsAssetInventory) {
        amsAssetInventory.setSn(amsReusingService.createSn());

        String addressIds = amsAssetInventory.getAddressIds();

        String useDeptIds = amsAssetInventory.getUseDeptIds();

        String ownDeptIds = amsAssetInventory.getOwnDeptIds();

        String assetStatus = amsAssetInventory.getAssetStatus();

        List<AmsOwnAsset> ownAssetList = amsOwnAssetService.list(new QueryWrapper<AmsOwnAsset>().
                in(addressIds != null && addressIds.length() > 0, AmsOwnAsset.ADDRESS_ID, addressIds.split(",")).
                in(useDeptIds != null && useDeptIds.length() > 0, AmsOwnAsset.USE_DEPT_ID, useDeptIds.split(",")).
                in(ownDeptIds != null && ownDeptIds.length() > 0, AmsOwnAsset.OWN_DEPT_ID, ownDeptIds.split(",")).
                eq(assetStatus != null, AmsOwnAsset.ASSET_STATUS, assetStatus));

        amsAssetInventory.setAssetTotalNum((long) ownAssetList.size());
        amsAssetInventoryService.insertAmsAssetInventory(amsAssetInventory);

        List<AmsAssetInventoryDetail> assetInventoryDetailList = new LinkedList<>();
        for (AmsOwnAsset ownAsset : ownAssetList) {
            AmsAssetInventoryDetail amsAssetInventoryDetail = new AmsAssetInventoryDetail();
            amsAssetInventoryDetail.setAssetId(ownAsset.getAssetId());
            amsAssetInventoryDetail.setInventoryId(amsAssetInventory.getInventoryId());
            amsAssetInventoryDetail.setStatus("0");
            assetInventoryDetailList.add(amsAssetInventoryDetail);
        }

        amsAssetInventoryDetailService.saveBatch(assetInventoryDetailList);

        return toAjax(1);
    }

    /**
     * 根据盘点主表id获取盘点单地各类状态盘点单数量
     */
    @GetMapping("/getInventoryNumberByInventoryId/{id}")
    public AjaxResult getInventoryNumberByInventoryId(@PathVariable(value = "id") Long id) {

        HashMap<String, Integer> inventoryNumberMap = new HashMap<>();
        inventoryNumberMap.put("inventorying", 0);
        inventoryNumberMap.put("inventoried", 0);
        inventoryNumberMap.put("inventoryLoss", 0);
        inventoryNumberMap.put("inventoryProfit", 0);

        List<AmsAssetInventoryDetail> list = amsAssetInventoryDetailService.list(new QueryWrapper<AmsAssetInventoryDetail>().eq(AmsAssetInventoryDetail.INVENTORY_ID, id));

        for (AmsAssetInventoryDetail assetInventoryDetail : list) {
            switch (assetInventoryDetail.getStatus()) {
                case "0":
                    inventoryNumberMap.put("inventorying", inventoryNumberMap.get("inventorying") + 1);
                    break;
                case "1":
                    inventoryNumberMap.put("inventoried", inventoryNumberMap.get("inventoried") + 1);
                    break;
                case "2":
                    inventoryNumberMap.put("inventoryLoss", inventoryNumberMap.get("inventoryLoss") + 1);
                    break;
                case "3":
                    inventoryNumberMap.put("inventoryProfit", inventoryNumberMap.get("inventoryProfit") + 1);
                    break;
            }
        }
        return AjaxResult.success(inventoryNumberMap);
    }

    /**
     * 修改盘点单
     */
    @PreAuthorize
    //@PreAuthorize(hasPermi = "ams:inventory:edit")
    @Log(title = "盘点单", businessType = BusinessType.UPDATE)
    //@ApiOperation(value = "修改盘点单")
    @PostMapping(value = "/editAmsAssetInventory")
    public AjaxResult editAmsAssetInventory(@RequestBody AmsAssetInventory amsAssetInventory) {
        return toAjax(amsAssetInventoryService.updateAmsAssetInventory(amsAssetInventory));
    }

    /**
     * 删除盘点单
     */
    @PreAuthorize
    //@PreAuthorize(hasPermi = "ams:inventory:remove")
    @Log(title = "盘点单", businessType = BusinessType.DELETE)
    @GetMapping("/removeAmsAssetInventorys")
    public AjaxResult removeAmsAssetInventorys(@RequestParam Long[] inventoryIds) {
        return toAjax(amsAssetInventoryService.deleteAmsAssetInventoryByInventoryIds(inventoryIds));
    }

    @GetMapping("/getAmsAssetInventoryNamesForSelect")
    //@ApiOperation(value = "获取盘点单名称列表用于下拉搜索")
    public AjaxResult getAmsAssetInventoryNamesForSelect() {
        List<AmsAssetInventory> list = amsAssetInventoryService.list();//自行加条件
        List<KeyValueVo> resultList = new ArrayList<>();
        for (AmsAssetInventory amsAssetInventory : list) {
            KeyValueVo vo = new KeyValueVo();
            //vo.setKey(it.getId());
            //vo.setValue(it.getName());
            resultList.add(vo);
        }
        return AjaxResult.success(resultList);
    }

    /**
     * 导出盘点单列表
     */
    @PreAuthorize
    //@PreAuthorize(hasPermi = "ams:inventory:export")
    @Log(title = "盘点单", businessType = BusinessType.EXPORT)
    @PostMapping("/exportAmsAssetInventory")
    public String exportAmsAssetInventory(HttpServletResponse response, AmsAssetInventory amsAssetInventory) throws IOException {
        List<AmsAssetInventory> list = amsAssetInventoryService.selectAmsAssetInventoryList(amsAssetInventory);
        ExcelUtil<AmsAssetInventory> util = new ExcelUtil<AmsAssetInventory>(AmsAssetInventory.class);
        util.exportExcel(response, list, "盘点单数据");
        return "";
    }

}
